import pageDesignerData from '~/externalResource/data.json'
import {
  searchComponents,
  getComponentChannels,
  batchSetChannelValue,
  updateComponentAssign
} from './components/index.js'
import { getInfluxdb, getInfluxdb2, writeChannel } from './influxdb/index'
import { format } from 'date-fns'
import lodash from 'lodash'
import { getConfigApi as cloudGetConfigApi } from '../cloud/config.js'
import faultAlertNameDict from './influxdb/faultAlertNameDict.json'
import { get } from '../http'

const response = (data: any) => {
  return new Promise(resolve => {
    resolve({
      code: 200,
      msg: data
    })
  })
}

// 获取配置
const getConfigApi = async (data: any) => {
  if (import.meta.env.MODE === 'base') {
    return cloudGetConfigApi(data)
  }
  const res: any = await get(
    `${window.location.origin}${
      import.meta.env.MODE === 'base' ? '/' : '/page-designer/'
    }externalResource/data.json?t=${new Date().getTime()}`
  )

  const pageDesignerData = res
  const { application, datasource, name } = data
  const result = pageDesignerData.filter((item: any) => {
    return (
      (item.application === application || !application) &&
      (item.datasource === datasource || !datasource) &&
      (item.name === name || !name)
    )
  })
  return response(result)
}

// 获取tag分组
const getDeviceTags = async (params: any) => {
  let { root_id } = params
  let path = `$[?((@.configGeneralConfig.stationId=='${root_id}' || @.configGeneralConfig.gridId=='${root_id}' || @.configGeneralConfig.cellId=='${root_id}') && @.configGeneralConfig.entity_type=='device')]`

  let keyHash = {
    'configGeneralConfig.stationId': 'stationId',
    'configGeneralConfig.gridId': 'gridId',
    'configGeneralConfig.cellId': 'cellId',
    'configGeneralConfig.stationName': 'stationName',
    'configGeneralConfig.gridName': 'gridName',
    'configGeneralConfig.cellName': 'cellName',
    'configGeneralConfig.cellExtraContent': 'cellExtraContent'
  }
  const res = await searchComponents({
    jsonpath: path,
    filter: Object.keys(keyHash)
  })
  res.data = res.data.map((item: any) => {
    for (let key in item) {
      item[keyHash[key as keyof typeof keyHash]] = item[key]
    }
    return item
  })
  let station_id = res.data[0].stationId
  let gridIds = res.data.map((item: any) => item.gridId)
  gridIds = [...new Set(gridIds)]

  const stationOne = res.data.find((i: any) => i.stationId === station_id && i.stationExtraContent)
  let result = [
    {
      id: station_id,
      item_label: res.data[0].stationName,
      item_extra_content: stationOne ? stationOne.stationExtraContent : '{}',
      children: gridIds.map((item: any) => {
        const findOne = res.data.find((i: any) => i.gridId === item)
        let cellIds = res.data.map((item: any) => item.cellId)
        cellIds = [...new Set(cellIds)]
        return {
          id: item,
          item_label: findOne.gridName,
          children: cellIds.map((cell_id: string) => {
            const findOne = res.data.find((i: any) => i.cellId === cell_id)
            return {
              id: cell_id,
              item_label: findOne.cellName,
              item_extra_content: findOne.cellExtraContent
            }
          })
        }
      })
    }
  ]
  return response(result)
}

// 查询设备
const getDevice = async (params: any) => {
  let { value, iot_id, category, componentId, entity_type = 'device', recursive, name, onlyData, manual_tag } = params
  let path = `(@.configGeneralConfig.stationId=='${value}' || @.configGeneralConfig.gridId=='${value}' || @.configGeneralConfig.cellId=='${value}') && @.configGeneralConfig.entity_type=='${entity_type}'`

  if (category) {
    path += ` && @.configGeneralConfig.productDict.product_category in ${JSON.stringify(category.split(','))}`
  }
  if (name) {
    path += ` && @.configGeneralConfig.alias=='${name}'`
  }
  if (iot_id) {
    path += ` && @.configGeneralConfig.iot_id in [${iot_id.split(',')}]`
  }
  if (componentId) {
    path = `@.componentId=='${componentId}'`
  }

  path = `$[?(${path})]`
  const res = await searchComponents({
    jsonpath: path,
    filter: ['configGeneralConfig', 'componentId']
  })

  if (manual_tag) {
    res.data = res.data.filter((item: any) => {
      const manualTags = item.configGeneralConfig.manual_tag.split(',')
      return manualTags.includes(manual_tag)
    })
  }

  const result = res.data.map((item: any) => {
    const {
      stationId,
      stationName,
      gridId,
      gridName,
      cellId,
      cellName,
      alias,
      productDict,
      iot_energyMeter,
      iot_productName,
      deviceNo,
      iot_id,
      parent_id,
      deviceId,
      cellExtraContent,
      stationExtraContent,
      groupTag,
      cell_category,
      domainId,
      entity_type,
      ...args
    } = item.configGeneralConfig
    return {
      id: deviceId,
      componentId: item.componentId,
      station_id: stationId,
      station_name: stationName,
      grid_id: gridId,
      grid_name: gridName,
      cell_id: cellId,
      cell_name: cellName,
      item_name: alias,
      item_device_no: deviceNo,
      item_iot_categoryname: productDict.product_category,
      item_iot_id: iot_id,
      item_energy_meter: iot_energyMeter,
      item_iot_productname: iot_productName,
      item_parent_id: parent_id,
      item_iot_general_config: JSON.stringify({ ...args, alias }),
      children: []
    }
  })
  if (recursive) {
    let arr: any = []
    result.forEach((item: any) => {
      if (item.item_parent_id) {
        const parent = result.find((val: any) => val.id === item.item_parent_id)
        if (parent) {
          parent.children.push(item)
        }
      } else {
        arr.push(item)
      }
    })
    return response(arr)
  }
  if (onlyData) {
    return result
  }
  return response(result)
}

// 查询控制器
const getController = async (params: any) => {
  return await getDevice({ ...params, entity_type: 'controller' })
}

// 查询功率设备
const getPowerDevice = async (params: any) => {
  const { value } = params
  let path = `$[?((@.configGeneralConfig.stationId=='${value}' || @.configGeneralConfig.gridId=='${value}' || @.configGeneralConfig.cellId=='${value}') && @.configGeneralConfig.entity_type=='device')]`

  const res = await searchComponents({
    jsonpath: path,
    filter: ['configGeneralConfig']
  })
  let result: any = {
    product_category: [],
    product_name: []
  }
  res.data.forEach((item: any) => {
    const { productDict, iot_productName } = item.configGeneralConfig
    if (!result.product_category.includes(productDict.product_category)) {
      result.product_category.push(productDict.product_category)
    }
    if (!result.product_name.includes(iot_productName)) {
      result.product_name.push(iot_productName)
    }
  })

  return response(result)
}

// 获取设备最后告警状态
const getAlarmLatestState = async (params: any) => {
  const { station_id, grid_id, cell_id } = params
  let deviceRes: any = await getDevice({ value: station_id || grid_id || cell_id, onlyData: true })
  const componentIds = deviceRes.map((item: any) => item.componentId)

  const res = await getInfluxdb(
    {
      inner_aggregate: 'last(`state`) state',
      component_ids: componentIds
    },
    'general_instant_query'
  )
  deviceRes.forEach((item: any) => {
    const findOne = res.find((val: any) => val[0].iot_id === item.item_iot_id)
    if (findOne) {
      item.state = findOne[0].state
      item.time = findOne[0].time
    }
  })

  return response(deviceRes)
}

// 查询计量设备
const getEnergyMeter = async (params: any) => {
  let { value, energy_type } = params

  let path = `$[?((@.configGeneralConfig.stationId=='${value}' || @.configGeneralConfig.gridId=='${value}' || @.configGeneralConfig.cellId=='${value}') && @.configGeneralConfig.entity_type=='device')]`

  const res = await searchComponents({
    jsonpath: path,
    filter: ['configGeneralConfig', 'componentId']
  })
  let devices = res.data.filter((item: any) => {
    const energy_meter = JSON.parse(item.configGeneralConfig.iot_energyMeter || '{}')
    if (energy_meter.energy_type && energy_meter.energy_type.length) {
      return energy_meter.energy_type.filter((val: any) => energy_type.includes(val)).length > 0
    }
    return false
  })
  const result: any = []
  devices.forEach((item: any) => {
    const {
      cell_category,
      cellExtraContent,
      cellId,
      cellName,
      gridId,
      gridName,
      stationId,
      stationName,
      deviceId,
      alias,
      iot_id,
      iot_productName,
      productDict,
      iot_energyMeter
    } = item.configGeneralConfig
    const findOne = result.find((val: any) => val.cell_id === cellId)
    const deviceObj = {
      id: deviceId,
      item_energy_meter: JSON.parse(iot_energyMeter),
      item_iot_categoryname: productDict.product_category,
      item_iot_id: iot_id,
      item_iot_productname: iot_productName,
      item_name: alias,
      componentId: item.componentId
    }
    if (findOne) {
      findOne.meters.push(deviceObj)
    } else {
      result.push({
        cell_category,
        cell_extra: JSON.parse(cellExtraContent),
        cell_id: cellId,
        cell_name: cellName,
        grid_id: gridId,
        grid_name: gridName,
        station_id: stationId,
        station_name: stationName,
        meters: [deviceObj]
      })
    }
  })
  return response(result)
}

const getDictionary = async (params: any, type: string) => {
  let path = ''
  if (type === 'iot_id') {
    path = `@.configGeneralConfig.iot_id=='${params}'`
  } else if (type === 'category') {
    path = `@.configGeneralConfig.productDict.product_category=='${params}'`
  }
  path = `$[?(${path})]`
  const res = await searchComponents({
    jsonpath: path,
    filter: ['configGeneralConfig.productDict']
  })
  return response(res.data[0]['configGeneralConfig.productDict'])
}

// 查询时序数据
const getDatapoolTsdb = async (params: any, name: string) => {
  const influxdb2Hash = ['general_instant_query']
  const res = await (influxdb2Hash.includes(name) ? getInfluxdb2(params, name) : getInfluxdb(params, name))
  let result = []
  if (res && res[0]) {
    result = res[0]
  }
  return response(result)
}
// 查询时序数据
const postSqlData = async (params: any, name: string) => {
  const res = await getInfluxdb(params, name)
  return response(res)
}

// 设置channel值
const setDeviceControl = async (req: any) => {
  let { componentId, iot_id, ...channels } = req.data[0]
  let data: any = []
  for (let key in channels) {
    data.push({
      channelId: lodash.upperFirst(lodash.camelCase(key)),
      value: channels[key]
    })
  }
  const res = await batchSetChannelValue(componentId, data)
  return res
}

const createOrUpdateData = async (req: any) => {
  let { componentId, item_iot_general_config } = req.data[0]

  const deviceRes = await searchComponents({
    jsonpath: `$[?(@.componentId=='${componentId}')]`,
    filter: ['configGeneralConfig', 'componentId']
  })
  delete deviceRes.data[0].configGeneralConfig.stopReason
  const data = [
    {
      name: 'general_config',
      value: {
        ...deviceRes.data[0].configGeneralConfig,
        ...JSON.parse(item_iot_general_config)
      }
    }
  ]
  const res = await updateComponentAssign(componentId, data)
  return res
}

// 创建操作日志
const submitOperationLog = async (req: any) => {
  const { type, data } = req
  const { iot_id, ...args } = data

  const res = await writeChannel({
    type,
    iotId: data.iot_id,
    ...args
  })
  console.log(res)
  return response(res)
}

// 查询channel历史数据
const getDeviceChannelTimeData = async (params: any) => {
  const res = await getInfluxdb(params, 'channel_time_data')
  return response(res[0])
}

// 设备告警
const getAlarmListAPI = async (params: any) => {
  const res = await getInfluxdb(params, 'device_event_records')
  res[0] = res[0] || []
  res[0] = res[0].map((item: any, index: number) => {
    let nameList = []
    for (let key in item) {
      if ((key.includes('Alert') || key.includes('Fault')) && item[key] === 1) {
        nameList.push(faultAlertNameDict[lodash.snakeCase(key).toUpperCase() as keyof typeof faultAlertNameDict] || key)
      }
    }
    return {
      serialNumber: index + 1,
      time: item.time,
      eventStatus: item.State === 2 ? '告警' : '故障',
      eventName: nameList.join(';'),
      deviceNo: item.alias
    }
  })
  return response(res[0])
}

const getOperationLogAPI = async (params: any) => {
  const { start_time, end_time } = params
  const res = await getInfluxdb(
    {
      startDateTime: start_time,
      endDateTime: end_time
    },
    'operation_log'
  )
  return response(res[0])
}

export default {
  getConfigApi,
  getDeviceTags,
  getDevice,
  getPowerDevice,
  getAlarmLatestState,
  getEnergyMeter,
  getController,
  getDictionary,
  getDatapoolTsdb,
  postSqlData,
  setDeviceControl,
  getDeviceChannelTimeData,
  getAlarmListAPI,
  createOrUpdateData,
  submitOperationLog,
  getOperationLogAPI
}
